Integration testing
When it comes to implement integration tests, there is a lot of debate. Aren't unit tests enough? What are you trying to cover with them?
- in the
Testsfolder, add a new xUnit project namedSpeakerService.Tests.Integration
We will add a helper class that extends WebApplicationFactory<TProgram>. This will allow us to configure a database used for tests(if- and we should use a different test database), and also allow us to create additional methods in-charge of channel creation.
Creating a custom Factory
public class MyFactory<TProgram> : WebApplicationFactory<TProgram> where
TProgram : class
{
}
- Configure the WebHost
Configure the WebHost
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("Test");
//builder.UseTestServer();
builder.ConfigureTestServices(services =>
{
//in here we configure what we need
});
builder.UseTestServer();
}
- Create an additional method that will return a gRPC client
CreateGrpcClient method
public SpeakerServiceDefinition.SpeakerServiceDefinitionClient CreateGrpcClient()
{
var httpClient = CreateClient();
var channel = GrpcChannel.ForAddress(httpClient.BaseAddress!, new GrpcChannelOptions
{
HttpClient = httpClient,
});
return new SpeakerServiceDefinition.SpeakerServiceDefinitionClient(channel);
}
Writing the test class
- add a class named
SpeakerServiceTeststhat extends ourMyFactoryclass
Title
public class SpeakerServiceTests : IClassFixture<MyFactory<Program>>
{
}
- prepare the constructor, passing the right
private readonly MyFactory<Program> factory;
public SpeakerServiceTests(MyFactory<Program> factory)
{
this.factory = factory;
}
- write the test method applying the AAA pattern
The test objects
We should work on a test database, that is seeded with some test data, or create some objects, insert them in the db, and then make assertions using them
- Arrange - call the factory to obtain a gRPC client, build an object that you know will be the response object
// Arrange
var client = factory.CreateGrpcClient();
var expectedResponse = new SpeakerResponse()
{
Id = 5,
City = "Oslo",
Country = "Norway",
Email = "",
Bio = "",
FirstName = "",
LastName = "",
Website = ""
};
- Act
Act
var response = await client.GetByIdAsync(new SpeakerFilterRequest { Id = 5 });
- Assert
Act
response.Should().BeEquivalentTo(expectedResponse);
DON't open
Full implementation
public class SpeakerServiceTests : IClassFixture<MyFactory<Program>>
{
private readonly MyFactory<Program> factory;
public SpeakerServiceTests(MyFactory<Program> factory)
{
this.factory = factory;
}
[Fact]
public async Task GetById_Async()
{
// Arrange
var client = factory.CreateGrpcClient();
var expectedResponse = new SpeakerResponse()
{
Id = 5,
City = "Oslo",
Country = "Norway",
Email = "",
Bio = "",
FirstName = "",
LastName = "",
Website = ""
};
var response = await client.GetByIdAsync(new SpeakerFilterRequest { Id = 5 });
// Assert
response.Should().BeEquivalentTo(expectedResponse);
}
}